package com.wc5818.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wc5818.dto.CurrentActiveItem;
import com.wc5818.wcComOrder.entity.WcComOrder;
import com.wc5818.wcComOrder.service.IWcComOrderService;
import com.wc5818.wcSysUser.entity.WcSysUser;
import com.wc5818.wcSysUser.mapper.WcSysUserMapper;
import com.wc5818.wcSysUser.service.IWcSysUserService;
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class WorkflowService {
    @Autowired
    WcSysUserMapper wcSysUserMapper;

    ProcessEngine processEngine;
    RepositoryService repositoryService;
    RuntimeService runtimeService;
    TaskService taskService;
    HistoryService historyService;

    public WorkflowService(@Value("${workflow.jdbcdriver}") String workflowJdbcDriver,
                           @Value("${workflow.jdbcurl}") String workflowJdbcUrl,
                           @Value("${workflow.username}") String workflowUserName,
                           @Value("${workflow.password}") String workflowPassword) {
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcDriver(workflowJdbcDriver)
                .setJdbcUrl(workflowJdbcUrl)
                .setJdbcUsername(workflowUserName)
                .setJdbcPassword(workflowPassword)
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
                .setHistory("full");

        this.processEngine = cfg.buildProcessEngine();

        String pName = processEngine.getName();
        String ver = ProcessEngine.VERSION;
        System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]");

        this.repositoryService = processEngine.getRepositoryService();

        this.runtimeService = processEngine.getRuntimeService();

        this.taskService = processEngine.getTaskService();

        this.historyService = processEngine.getHistoryService();

    }

    String getGapTime(long millis) {
        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);

        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }


    public List<CurrentActiveItem> assembleList(String processDefinitionId, String processId) {
        // 全流程列表
        List<CurrentActiveItem> list1 = processCurrentStep(processDefinitionId);
        // 已经流转了几个结点的流程列表
        List<HistoricActivityInstance> list2 = historyActivityInstance(processId);

        list1.forEach(element -> {
            element.setStatus("未到达");
            element.setFullMessage("");
        });

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        for (HistoricActivityInstance historicActivityInstance : list2
        ) {
            for (CurrentActiveItem currentActiveItem : list1) {
                System.out.println(currentActiveItem.getActivityId() + "\t\t\t" + historicActivityInstance.getActivityId());

                if (currentActiveItem.getActivityId().equals(historicActivityInstance.getActivityId())) {
                    currentActiveItem.setAssignee("系统");
                    String assigneeId = historicActivityInstance.getAssignee() == null ? "" : historicActivityInstance.getAssignee();
                    if (assigneeId != null) {
                        WcSysUser wcSysUser = wcSysUserMapper.selectById(assigneeId);
                        if (wcSysUser != null)
                            currentActiveItem.setAssignee(wcSysUser.getRealName() == null ? "" : wcSysUser.getRealName());
                    }

                    currentActiveItem.setStartTime(historicActivityInstance.getStartTime() == null ? "" : sdf.format(historicActivityInstance.getStartTime()));
                    currentActiveItem.setEndTime(historicActivityInstance.getEndTime() == null ? "" : sdf.format(historicActivityInstance.getEndTime()));
                    currentActiveItem.setDuration(historicActivityInstance.getDurationInMillis() == null ? "" : getGapTime(historicActivityInstance.getDurationInMillis()).toString());
                    currentActiveItem.setAudit(true);
                    currentActiveItem.setStatus("已完成");

                    // 审批意见
                    String historytaskId = historicActivityInstance.getTaskId();
                    List<Comment> comments = taskService.getTaskComments(historytaskId);
                    if(comments != null && comments.size() > 0)
                        currentActiveItem.setFullMessage(comments.get(0).getFullMessage());


                    break;
                }
            }
        }

        list1.get(list2.size() - 1).setStatus("处理中");

        return list1;
    }

    // 全流程结点列表
    public List<CurrentActiveItem> processCurrentStep(String processDefinitionId) {
        List<CurrentActiveItem> list = new ArrayList<>();

        BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
        if (model != null) {
            Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
            for (FlowElement e : flowElements) {
                System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() + "   class:" + e.getClass().toString());

                if (e.getClass().equals(UserTask.class) || e.getClass().equals(StartEvent.class) || e.getClass().equals(EndEvent.class)) {
                    CurrentActiveItem currentActiveItem = new CurrentActiveItem();
                    currentActiveItem.setActivityId(e.getId());
                    currentActiveItem.setActivityName(e.getName());
                    list.add(currentActiveItem);
                }
            }
        }

        return list;
    }

    public void deleteDeployment(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId);
        System.out.println("deleteDeployment ok");
    }

    public String deployment(String bpmnName) {
        Deployment deployment = repositoryService.createDeployment().addClasspathResource(bpmnName).deploy();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
        if (processDefinition != null) {
            return processDefinition.getKey();
        }
        return null;
    }

    public String startNewProcess(String key, Map<String, Object> param) {
        ProcessInstance processInstance = this.runtimeService.startProcessInstanceByKey(key, param);
        if (processInstance != null) {
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstance.getId())//使用流程实例ID
//                    .taskAssignee(param.get("yewyId") + "")//任务办理人
                    .singleResult();

            //设置流程变量, 为了后面的订单能拿到业务数据
            taskService.setVariable(task.getId(), "车友订单号", param.get("ordernum"));
            return processInstance.getProcessDefinitionId() + ";" + processInstance.getId();
        }

        return null;
    }

    @Autowired
    IWcComOrderService iWcComOrderService;

    // 当前的任务列表， “待处理”
    public List<WcComOrder> taskList(String userId) {
        List<WcComOrder> out = new ArrayList<>();

        TaskQuery taskQuery = taskService.createTaskQuery();
        if (userId != null) {
            taskQuery.taskAssignee(userId).orderByTaskCreateTime().desc();
        }

        //办理人的任务列表
        List<Task> list = taskQuery.list();
        //遍历任务列表
        if (list != null && list.size() > 0) {
            String ordernum = null;

            for (Task task : list) {
                System.out.println("任务创建时间：" + task.getCreateTime());
                System.out.println("任务处理人：" + task.getAssignee());
                System.out.println("任务id：" + task.getId());
                System.out.println("任务名称：" + task.getName());
                System.out.println("流程变量：" + taskService.getVariable(task.getId(), "车友订单号"));
                System.out.println("审批意见：" + taskService.getTaskComments(task.getId()));
                System.out.println();

                // 流程变量中取出订单号
                ordernum = taskService.getVariable(task.getId(), "车友订单号") + "";
                WcComOrder wcComOrder = iWcComOrderService.getOne(new QueryWrapper<WcComOrder>().eq("ordernum", ordernum), false);
                if (wcComOrder != null) {
                    wcComOrder.setTaskName(task.getName());
                    wcComOrder.setTaskId(task.getId());
                    out.add(wcComOrder);
                }
            }
        }

        return out;
    }

    // 历史任务列表，“已处理”
    public List<WcComOrder> taskList4History(String userId) {
        List<WcComOrder> out = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        HistoricTaskInstanceQuery htiq = this.historyService.createHistoricTaskInstanceQuery();
        htiq.taskAssignee(userId);
        List<HistoricTaskInstance> tasks = htiq.orderByHistoricTaskInstanceStartTime().desc().list();

        for (HistoricTaskInstance hti : tasks) {
            String pid = hti.getProcessInstanceId();
            List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(pid).list();
            for (HistoricVariableInstance historicVariableInstance: list
                 ) {
                if(historicVariableInstance.getVariableName().equals("车友订单号")) {
                    System.out.print(sdf.format(hti.getStartTime()));
                    System.out.print("\t\t\t");
                    System.out.print(historicVariableInstance.getValue());
                    System.out.println();

                    WcComOrder wcComOrder = iWcComOrderService.getOne(new QueryWrapper<WcComOrder>().eq("ordernum", historicVariableInstance.getValue()), false);
                    if (wcComOrder != null) {
                        wcComOrder.setTaskName(hti.getName());
                        wcComOrder.setTaskId(hti.getId());
                        out.add(wcComOrder);
                    }
                }
            }

        }

        return out;
    }

    public String claim(String taskId, String userId) {
        taskService.claim(taskId, userId);
        return "用户: " + userId + " 认领, " + taskId;
    }

    public void complete(String taskId, Map<String, Object> map) throws RuntimeException {
        try {
            taskService.addComment(taskId, null, map.get("comment") + "");
            // map 给下个节点传递的参数
            taskService.complete(taskId, map);

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public Object history(String userId) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        for (HistoricTaskInstance historicTaskInstance : list
        ) {
            System.out.println(historicTaskInstance.getProcessVariables().get("车友订单号"));
        }

        return list;
    }

    // 流程实例id查询历史活动
    public List<HistoricActivityInstance> historyActivityInstance(String processId) {
        HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
        historicActivityInstanceQuery.processInstanceId(processId);
        historicActivityInstanceQuery.orderByHistoricActivityInstanceStartTime().asc();

        List<HistoricActivityInstance> list = historicActivityInstanceQuery.list();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        for (HistoricActivityInstance historicActivityInstance : list
        ) {
            System.out.println(historicActivityInstance.getActivityId() + "\t" + historicActivityInstance.getActivityName() + "\t" + sdf.format(historicActivityInstance.getStartTime()));
        }

        return list;
    }

    InputStream currentProcessInstanceImage(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        // ID 为 流程定义Key
        Process process = bpmnModel.getProcessById(processDefinition.getKey());

        // 流程节点ID
        FlowElement flowElement = process.getFlowElement(task.getTaskDefinitionKey());

        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        List<String> highLightedActivities = new ArrayList<>();
        highLightedActivities.add(flowElement.getId());


        InputStream inputStream = generator.generateDiagram(bpmnModel, "jpg", highLightedActivities, Collections.emptyList(), "宋体", "宋体", "宋体", null, 2.0);
        return inputStream;
    }

    // 高亮当前点，带历史路径的流程图图片
    public void runWhere(String pProcessInstanceId, HttpServletResponse response) throws Exception {
        InputStream is = currentProcessInstanceImage("20");
        System.out.println();

        ServletOutputStream sos = response.getOutputStream();
        byte[] bytes = new byte[1024 * 1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1) {
            sos.write(bytes, 0, len);
        }

        sos.flush();
    }

    public Object deleteAllTask(String userId) {
        Map<String, Object> map = new HashMap<>();

        List<Task> list = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        for (Task task : list
        ) {
            try {
                String processInstanceId = task.getProcessInstanceId();
                runtimeService.deleteProcessInstance(processInstanceId, "删除垃圾数据");
                System.out.println("没出异常，证明删除成功");

            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

        return "已清空所有任务";
    }
}
